#include "rl_utility.h"
#include <cmath>
#include <boost/test/included/unit_test.hpp>

void test_rl_utility() {
	// rand methods
	const int times = 1e6;
	for (int i = 0; i < times; ++i) {
		int result = RLUtility::Rand0A(10);
		BOOST_CHECK(result >= 0 && result < 10);
		
		result = RLUtility::RandAB(10, 20);
		BOOST_CHECK(result >= 10 && result < 20);
		
		double unit_result = RLUtility::RandUnit();
		BOOST_CHECK(unit_result >= 0 && unit_result <= 1);
	}
	
	//
	const double threshold = 0.1e6;
	int elements = 50;
	double* density_array = new double[elements];
	CNCSparseRowColumn<double> sparse_array;
	std::vector<int> index;
	for (int i = 0; i < elements; ++i) {
		density_array[i] = 0.0;
		
		if (i != 10 && i != 45) {
			index.push_back(i);
		}
	}
	density_array[5] = 3.0;		sparse_array.add(5, 3.0);
	density_array[10] = 10.0;	sparse_array.add(10, 10.0);
	density_array[15] = 2.0;		sparse_array.add(15, 2.0);
	density_array[20] = 5.0;		sparse_array.add(20, 5.0);
	density_array[25] = 0.9;		sparse_array.add(25, 0.9);
	density_array[30] = -81;		sparse_array.add(30, -81);
	density_array[35] = -56;		sparse_array.add(35, -56);
	density_array[40] = 5.0;		sparse_array.add(40, 5.0);
	density_array[45] = 10.0;	sparse_array.add(45, 10.0);
	
	// test Max
	BOOST_CHECK(std::abs(RLUtility::Max(density_array, elements) - 10.0) < threshold);
	BOOST_CHECK(std::abs(RLUtility::Max(sparse_array) - 10.0) < threshold);
	
	// test ArgMax
	BOOST_CHECK_EQUAL(RLUtility::ArgMax(density_array, elements), 10);
	BOOST_CHECK_EQUAL(RLUtility::ArgMax(sparse_array), 10);
	
	// test ArgMaxAll
	std::vector<int> all_args = RLUtility::ArgMaxAll(density_array, elements);
	BOOST_CHECK_EQUAL(all_args.size(), 2);
	BOOST_CHECK_EQUAL(all_args[0], 10);
	BOOST_CHECK_EQUAL(all_args[1], 45);
	
	all_args.clear();
	all_args = RLUtility::ArgMaxAll(sparse_array);
	BOOST_CHECK_EQUAL(all_args.size(), 2);
	BOOST_CHECK_EQUAL(all_args[0], 10);
	BOOST_CHECK_EQUAL(all_args[1], 45);
	
	// cut two elements of sparse array
	sparse_array.add(10, -density_array[10]);
	sparse_array.add(45, -density_array[45]);
	
	// test Max with index
	BOOST_CHECK(std::abs(RLUtility::Max(density_array, index) - 5.0) < threshold);
	BOOST_CHECK(std::abs(RLUtility::Max(sparse_array) - 5.0) < threshold);
	
	// test ArgMax with index
	BOOST_CHECK_EQUAL(RLUtility::ArgMax(density_array, index), 20);
	BOOST_CHECK_EQUAL(RLUtility::ArgMax(sparse_array), 20);
	
	// test ArgMaxAll with index
	all_args.clear();
	all_args = RLUtility::ArgMaxAll(density_array, index);
	BOOST_CHECK_EQUAL(all_args.size(), 2);
	BOOST_CHECK_EQUAL(all_args[0], 20);
	BOOST_CHECK_EQUAL(all_args[1], 40);
	
	all_args.clear();
	all_args = RLUtility::ArgMaxAll(sparse_array);
	BOOST_CHECK_EQUAL(all_args.size(), 2);
	BOOST_CHECK_EQUAL(all_args[0], 20);
	BOOST_CHECK_EQUAL(all_args[1], 40);
	
	delete[] density_array;
}